`include "PRV564Config.v"
`include "PRV564Define.v"
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Date    : 2021/8/15                                                                         //
//  Author  : Jack.Pan                                                                          //
//  Desc    : Commit unit for PRV564 processor(pre-manage interrupt and write back information) //
//  Version : 0.0(Orignal)                                                                      //
//////////////////////////////////////////////////////////////////////////////////////////////////
module commit(
    input wire              Global_CLK,
    input wire              Global_ARST,
//-------------------Interrupt------------------
    input wire              NMI_EccErr, NMI_PwrLost, NMI_generic,
//-----------------CSR value input--------------
    input wire [`XLEN-1:0]  CSR_mideleg, CSR_medeleg,
    input wire [`XLEN-1:0]  CSR_mip, CSR_mie,
    input wire              CSR_mige, CSR_sige,
    input wire              Global_Flush,
//-------------------pipline 0 input--------------------------
    input  wire             PIP0i_MSC_valid,
    input  wire             PIP0i_MSC_LoadPageFlt,
    input  wire             PIP0i_MSC_LoadAccFlt,
    input  wire             PIP0i_MSC_LoadAddrMis,
    input  wire             PIP0i_MSC_StorePageFlt,
    input  wire             PIP0i_MSC_StoreAccFlt,
    input  wire             PIP0i_MSC_StoreAddrMis,
    input  wire             PIP0i_INFO_ci,
    input  wire [7:0]       PIP0i_INFO_itag,
    input  wire [`XLEN-1:0] PIP0i_INFO_pc,
    input  wire [1:0]       PIP0i_INFO_priv,
    input  wire [`XLEN-1:0] PIP0i_DATA_data1,
    input  wire [`XLEN-1:0] PIP0i_DATA_data2,
    output wire             PIP0o_FC_ready,
//------------------pipline 1 input-----------------------------
    input  wire             PIP1i_MSC_valid,
    input  wire             PIP1i_MSC_LoadPageFlt,
    input  wire             PIP1i_MSC_LoadAccFlt,
    input  wire             PIP1i_MSC_LoadAddrMis,
    input  wire             PIP1i_MSC_StorePageFlt,
    input  wire             PIP1i_MSC_StoreAccFlt,
    input  wire             PIP1i_MSC_StoreAddrMis,
    input  wire             PIP1i_INFO_ci,
    input  wire [7:0]       PIP1i_INFO_itag,
    input  wire [`XLEN-1:0] PIP1i_INFO_pc,
    input  wire [1:0]       PIP1i_INFO_priv,
    input  wire [`XLEN-1:0] PIP1i_DATA_data1,
    input  wire [`XLEN-1:0] PIP1i_DATA_data2,
    output wire             PIP1o_FC_ready,
//------------------pipline 2 input-----------------------------
    input  wire             PIP2i_MSC_valid,
    input  wire             PIP2i_MSC_LoadPageFlt,
    input  wire             PIP2i_MSC_LoadAccFlt,
    input  wire             PIP2i_MSC_LoadAddrMis,
    input  wire             PIP2i_MSC_StorePageFlt,
    input  wire             PIP2i_MSC_StoreAccFlt,
    input  wire             PIP2i_MSC_StoreAddrMis,
    input  wire             PIP2i_INFO_ci,
    input  wire [7:0]       PIP2i_INFO_itag,
    input  wire [`XLEN-1:0] PIP2i_INFO_pc,
    input  wire [1:0]       PIP2i_INFO_priv,
    input  wire [`XLEN-1:0] PIP2i_DATA_data1,
    input  wire [`XLEN-1:0] PIP2i_DATA_data2,
    output wire             PIP2o_FC_ready,
//-------------------DITF read port------------------------------
    input  wire             DITFo_v,                    //current entry is valid
    input  wire [7:0]       DITFo_itag,                 //当前待写回指令的tag
//  input  wire [4:0]       DITFo_rs1index,             //Not use
//  input  wire             DITFo_rs1en,
//  input  wire [4:0]       DITFo_rs2index,
//  input  wire             DITFo_rs2en,
    input  wire [4:0]       DITFo_rdindex,
    input  wire             DITFo_rden,                 //GPR 写回使能
    input  wire [11:0]      DITFo_csrindex,
    input  wire             DITFo_csren,                //CSR 写回使能
    input  wire             DITFo_jmp,
    input  wire             DITFo_InsAccessFlt,
    input  wire             DITFo_InsPageFlt,
    input  wire             DITFo_InsAddrMis,
    input  wire             DITFo_illins,
    input  wire             DITFo_mret,
    input  wire             DITFo_sret,
    input  wire             DITFo_ecall,
    input  wire             DITFo_ebreak,
    input  wire             DITFo_fence,
    input  wire             DITFo_fencei,
    input  wire             DITFo_fencevma,
    input  wire             DITFo_system,
    output wire             DITFi_remove,               //从DITF中移除表项
//---------------------To write back---------------------
    output  reg             CMT_valid,
    output  reg             CMT_GPRwen,
    output  reg [4:0]       CMT_GPRwindex,
    output  reg [`XLEN-1:0] CMT_data1,
    output  reg [`XLEN-1:0] CMT_data2,
    output  reg             CMT_csren,
    output  reg [11:0]      CMT_csrindex,
    output  reg [`XLEN-1:0] CMT_pc,                      //当前正在写回的PC
	output  reg [1:0]       CMT_priv,
    output  reg             CMT_ci,                     //当前指令是否为CI=1的指令，即MMIO指令
    //----------target mode and exception code-----
    output reg [`XLEN-1:0]  CMT_trap_value, CMT_trap_cause, CMT_trap_pc,
    output reg              CMT_trap_s, CMT_trap_m, CMT_trap_async,               //trap target to m mode or s mode, and if the trap is async trap
    output reg              CMT_mret,
    output reg              CMT_sret,
    output  reg             CMT_fence,
    output  reg             CMT_fencei,
    output  reg             CMT_fencevma,
    output  reg             CMT_system
);
// write back
    wire             WB_valid;
    wire             WB_rden;
    wire [4:0]       WB_rdindex;
    wire [`XLEN-1:0] WB_data1;
    wire             WB_csren;
    wire [11:0]      WB_csrindex;
    wire [`XLEN-1:0] WB_data2;
    wire [`XLEN-1:0] WB_pc;                      //当前正在写回的PC
	wire [1:0]       WB_priv;
    wire             WB_ci;
    wire             WB_jmp;
    wire             WB_InstAccFlt;
    wire             WB_InstPageFlt;
    wire             WB_InstAddrMis;
    wire             WB_LoadAccFlt;
    wire             WB_LoadPageFlt;
    wire             WB_LoadAddrMis;
    wire             WB_StoreAccFlt;
    wire             WB_StorePageFlt;
    wire             WB_StoreAddrMis;
    wire             WB_illins;
    wire             WB_mret;
    wire             WB_sret;
    wire             WB_ecall;
    wire             WB_ebreak;
    wire             WB_fence;
    wire             WB_fencei;
    wire             WB_fencevma;
    wire             WB_system;
// trap cause and value
    wire [`XLEN-1:0] trap_cause,    trap_value, trap_pc;
    wire             trap_m,        trap_s,     trap_async;
WB_select               WB_select(
    .Global_Flush                (Global_Flush),
    .PIP0i_MSC_valid             (PIP0i_MSC_valid),
    .PIP0i_MSC_LoadPageFlt       (PIP0i_MSC_LoadPageFlt),
    .PIP0i_MSC_LoadAccFlt        (PIP0i_MSC_LoadAccFlt),
    .PIP0i_MSC_LoadAddrMis       (PIP0i_MSC_LoadAddrMis),
    .PIP0i_MSC_StorePageFlt      (PIP0i_MSC_StorePageFlt),
    .PIP0i_MSC_StoreAccFlt       (PIP0i_MSC_StoreAccFlt),
    .PIP0i_MSC_StoreAddrMis      (PIP0i_MSC_StoreAddrMis),
    .PIP0i_INFO_ci               (PIP0i_INFO_ci),
    .PIP0i_INFO_itag             (PIP0i_INFO_itag),
    .PIP0i_INFO_pc               (PIP0i_INFO_pc),
    .PIP0i_INFO_priv             (PIP0i_INFO_priv),
    .PIP0i_DATA_data1            (PIP0i_DATA_data1),
    .PIP0i_DATA_data2            (PIP0i_DATA_data2),
    .PIP0o_FC_ready              (PIP0o_FC_ready),
    //-----------pipline 1---------------
    .PIP1i_MSC_valid             (PIP1i_MSC_valid),
    .PIP1i_MSC_LoadPageFlt       (PIP1i_MSC_LoadPageFlt),
    .PIP1i_MSC_LoadAccFlt        (PIP1i_MSC_LoadAccFlt),
    .PIP1i_MSC_LoadAddrMis       (PIP1i_MSC_LoadAddrMis),
    .PIP1i_MSC_StorePageFlt      (PIP1i_MSC_StorePageFlt),
    .PIP1i_MSC_StoreAccFlt       (PIP1i_MSC_StoreAccFlt),
    .PIP1i_MSC_StoreAddrMis      (PIP1i_MSC_StoreAddrMis),
    .PIP1i_INFO_ci               (PIP1i_INFO_ci),
    .PIP1i_INFO_itag             (PIP1i_INFO_itag),
    .PIP1i_INFO_pc               (PIP1i_INFO_pc),
    .PIP1i_INFO_priv             (PIP1i_INFO_priv),
    .PIP1i_DATA_data1            (PIP1i_DATA_data1),
    .PIP1i_DATA_data2            (PIP1i_DATA_data2),
    .PIP1o_FC_ready              (PIP1o_FC_ready),
    //-------------pipline 2-----------------
    .PIP2i_MSC_valid             (PIP2i_MSC_valid),
    .PIP2i_MSC_LoadPageFlt       (PIP2i_MSC_LoadPageFlt),
    .PIP2i_MSC_LoadAccFlt        (PIP2i_MSC_LoadAccFlt),
    .PIP2i_MSC_LoadAddrMis       (PIP2i_MSC_LoadAddrMis),
    .PIP2i_MSC_StorePageFlt      (PIP2i_MSC_StorePageFlt),
    .PIP2i_MSC_StoreAccFlt       (PIP2i_MSC_StoreAccFlt),
    .PIP2i_MSC_StoreAddrMis      (PIP2i_MSC_StoreAddrMis),
    .PIP2i_INFO_ci               (PIP2i_INFO_ci),
    .PIP2i_INFO_itag             (PIP2i_INFO_itag),
    .PIP2i_INFO_pc               (PIP2i_INFO_pc),
    .PIP2i_INFO_priv             (PIP2i_INFO_priv),
    .PIP2i_DATA_data1            (PIP2i_DATA_data1),
    .PIP2i_DATA_data2            (PIP2i_DATA_data2),
    .PIP2o_FC_ready              (PIP2o_FC_ready),
    //--------------DITF port-----------------
    .DITFo_v                     (DITFo_v),
    .DITFo_itag                  (DITFo_itag),
    .DITFo_rdindex               (DITFo_rdindex),
    .DITFo_rden                  (DITFo_rden),
    .DITFo_csrindex              (DITFo_csrindex),
    .DITFo_csren                 (DITFo_csren),
    .DITFo_jmp                   (DITFo_jmp),
    .DITFo_InsAccessFlt          (DITFo_InsAccessFlt),
    .DITFo_InsPageFlt            (DITFo_InsPageFlt),
    .DITFo_InsAddrMis            (DITFo_InsAddrMis),
    .DITFo_illins                (DITFo_illins),
    .DITFo_mret                  (DITFo_mret),
    .DITFo_sret                  (DITFo_sret),
    .DITFo_ecall                 (DITFo_ecall),
    .DITFo_ebreak                (DITFo_ebreak),
    .DITFo_fence                 (DITFo_fence),
    .DITFo_fencei                (DITFo_fencei),
    .DITFo_fencevma              (DITFo_fencevma),
    .DITFo_system                (DITFo_system),
    .DITFi_remove                (DITFi_remove),
    //----------------Write Back----------------
    .WB_valid                    (WB_valid),
    .WB_rden                     (WB_rden),
    .WB_rdindex                  (WB_rdindex),
    .WB_data1                    (WB_data1),
    .WB_csren                    (WB_csren),
    .WB_csrindex                 (WB_csrindex),
    .WB_data2                    (WB_data2),
    .WB_pc                       (WB_pc),
    .WB_priv                     (WB_priv),
    .WB_jmp                      (WB_jmp),
    .WB_ci                       (WB_ci),
    .WB_InsAccFlt                (WB_InstAccFlt),
    .WB_InsPageFlt               (WB_InstPageFlt),
    .WB_InsAddrMis               (WB_InstAddrMis),
    .WB_LoadAccFlt               (WB_LoadAccFlt),
    .WB_LoadPageFlt              (WB_LoadPageFlt),
    .WB_LoadAddrMis              (WB_LoadAddrMis),
    .WB_StoreAccFlt              (WB_StoreAccFlt),
    .WB_StorePageFlt             (WB_StorePageFlt),
    .WB_StoreAddrMis             (WB_StoreAddrMis),
    .WB_illins                   (WB_illins),
    .WB_mret                     (WB_mret),
    .WB_sret                     (WB_sret),
    .WB_ecall                    (WB_ecall),
    .WB_ebreak                   (WB_ebreak),
    .WB_fence                    (WB_fence),
    .WB_fencei                   (WB_fencei),
    .WB_fencevma                 (WB_fencevma),
    .WB_system                   (WB_system)
);
TrapManage   TrapManage(
//---------current privilege and pc, virtual address input---------
    .instr_pc           (WB_pc), 
    .instr_VA           (WB_data2), 
    .instr_jmpaddr      (WB_data2),
    .instr_priv         (WB_priv),
    .instr_jmp          (WB_jmp),
    .instr_system       (WB_system),
//--------None Maskable interrupt------
    .NMI_EccErr         (NMI_EccErr), 
    .NMI_PwrLost        (NMI_PwrLost), 
    .NMI_generic        (NMI_generic),
//--------Interrput input and enable--------------
    .mige               (CSR_mige), 
    .sige               (CSR_sige),                     //Machine and Supervisior interrupt globally enable
    .mei                (CSR_mip[11]),  
    .sei                (CSR_mip[9]),                   //Machine and Supervisior mode external interrupt pending
    .meie               (CSR_mie[11]), 
    .seie               (CSR_mie[9]),                   //Machine and Supervisior mode external interrupt enable
    .mti                (CSR_mip[7]),  
    .sti                (CSR_mip[5]),                   //Machine and Supervisior mode timer interrupt
    .mtie               (CSR_mie[7]), 
    .stie               (CSR_mie[5]),
    .msi                (CSR_mip[3]),  
    .ssi                (CSR_mip[1]),                   //Machine and Supervisior mode software interrupt
    .msie               (CSR_mie[3]), 
    .ssie               (CSR_mie[1]),
//----------exception input------------
    .ecall              (WB_ecall), 
    .ebreak             (WB_ebreak),                         //environment call and break
    .ill_ins            (WB_illins),                         //illeagal instructions
    .InstPageFlt        (WB_InstPageFlt), 
    .InstAddrMis        (WB_InstAddrMis), 
    .InstAccFlt         (WB_InstAccFlt),
    .LoadPageFlt        (WB_LoadPageFlt), 
    .LoadAddrMis        (WB_LoadAddrMis), 
    .LoadAccFlt         (WB_LoadAccFlt),
    .StorePageFlt       (WB_StorePageFlt),
    .StoreAddrMis       (WB_StoreAddrMis),
    .StoreAccFlt        (WB_StoreAccFlt),
//-----------mideleg and medeleg---------------
    .csr_mideleg        (CSR_mideleg), 
    .csr_medeleg        (CSR_medeleg),
//----------target mode and exception code-----
    .trap_value         (trap_value), 
    .trap_cause         (trap_cause), 
    .trap_pc            (trap_pc),
    .trap_s             (trap_s), 
    .trap_m             (trap_m), 
    .trap_async         (trap_async)
);
//-------------------output DFF-------------------
always@(posedge Global_CLK or posedge Global_ARST)begin
    if(Global_ARST)begin
        CMT_valid       <= 1'b0;
        CMT_GPRwen      <= 1'b0;
        CMT_GPRwindex   <= 5'hx;
        CMT_data1       <= 64'hx;
        CMT_data2       <= 64'hx;
        CMT_csren       <= 1'b0;
        CMT_csrindex    <= 12'hx;
        CMT_pc          <= 64'hx;       //当前正在写回的PC
	    CMT_priv        <= 64'hx;
        CMT_ci          <= 1'bx;
    //----------target mode and exception code-----
        CMT_trap_value  <= 64'hx;
        CMT_trap_cause  <= 64'hx;
        CMT_trap_pc     <= 64'hx;
        CMT_trap_s      <= 1'b0;
        CMT_trap_m      <= 1'b0;
        CMT_trap_async  <= 1'b0;         //trap target to m mode or s mode, and if the trap is async trap
        CMT_mret        <= 1'b0;
        CMT_sret        <= 1'b0;
        CMT_fence       <= 1'b0;
        CMT_fencei      <= 1'b0;
        CMT_fencevma    <= 1'b0;
        CMT_system      <= 1'b0;
    end
    else if(Global_Flush)begin
        CMT_valid       <= 1'b0;
        CMT_GPRwen      <= 1'b0;
        CMT_GPRwindex   <= 5'hx;
        CMT_data1       <= 64'hx;
        CMT_data2       <= 64'hx;
        CMT_csren       <= 1'b0;
        CMT_csrindex    <= 12'hx;
        CMT_pc          <= 64'hx;       //当前正在写回的PC
	    CMT_priv        <= 64'hx;
        CMT_ci          <= 1'b0;
    //----------target mode and exception code-----
        CMT_trap_value  <= 64'hx;
        CMT_trap_cause  <= 64'hx;
        CMT_trap_pc     <= 64'hx;
        CMT_trap_s      <= 1'b0;
        CMT_trap_m      <= 1'b0;
        CMT_trap_async  <= 1'b0;         //trap target to m mode or s mode, and if the trap is async trap
        CMT_mret        <= 1'b0;
        CMT_sret        <= 1'b0;
        CMT_fence       <= 1'b0;
        CMT_fencei      <= 1'b0;
        CMT_fencevma    <= 1'b0;
        CMT_system      <= 1'b0;
    end
    else begin
        CMT_valid       <= WB_valid;
        CMT_GPRwen      <= WB_valid & WB_rden;
        CMT_GPRwindex   <= WB_rdindex;
        CMT_data1       <= WB_data1;
        CMT_data2       <= WB_data2;
        CMT_csren       <= WB_valid & WB_csren;
        CMT_csrindex    <= WB_csrindex;
        CMT_pc          <= WB_pc;       //当前正在写回的PC
	    CMT_priv        <= WB_priv;
        CMT_ci          <= WB_valid & WB_ci;
    //----------target mode and exception code-----
        CMT_trap_value  <= trap_value;
        CMT_trap_cause  <= trap_cause;
        CMT_trap_pc     <= trap_pc;
        CMT_trap_s      <= WB_valid & trap_s;
        CMT_trap_m      <= WB_valid & trap_m;
        CMT_trap_async  <= WB_valid & trap_async;         //trap target to m mode or s mode, and if the trap is async trap
        CMT_mret        <= WB_valid & WB_mret;
        CMT_sret        <= WB_valid & WB_sret;
        CMT_fence       <= WB_valid & WB_fence;
        CMT_fencei      <= WB_valid & WB_fencei;
        CMT_fencevma    <= WB_valid & WB_fencevma;
        CMT_system      <= WB_valid & WB_system;
    end
end
endmodule
